// 11.3 关联容器操作
/**
 * 除了表9.2（第295页）中列出的类型，关联容器还定义了表11.3中列出的类型。这些类型表示容器关键字和值的类型。[插图]
 * 1. key_type     此容器类型的关键字类型
 * 2. mapped_type  每个关键字关联的类型，即值的类型，只适用于map
 * 3. value_type   对于set，与key_type相同；对于map，为pair<const key_type,mapped_type>
 * 与顺序容器一样（参见9.2.2节，第297页），我们使用作用域运算符来提取一个类型的成员——例如，map<string，int>：：key_type。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
using namespace std;

int main()
{
    // 11.3.2 添加元素
    // 关联容器的insert成员（见表11.4，第384页）向容器中添加一个元素或一个元素范围。
    vector<int> ivec = {2, 4, 6, 8, 2, 4, 6, 8}; // ivec有8个元素
    set<int> set2;
    set2.insert(ivec.cbegin(), ivec.cend()); // set2有4个元素
    set2.insert({1, 3, 5, 7, 1, 3, 5, 7});   // set2现在有8个元素

    // 向map添加元素
    map<string,size_t> word_count;
    word_count.insert({"hello",1});
    word_count.insert(make_pair("hello",1));
    word_count.insert(pair<string,size_t>("hello",1));
    word_count.insert(map<string, size_t>::value_type("hello", 1));
    // 向word_count插入元素的4种方法，显然前两种要简便一些

    // 检测insert的返回值
    // 检测insert的返回值insert（或emplace）返回的值依赖于容器类型和参数。
    // 对于不包含重复关键字的容器，添加单一元素的insert和emplace版本返回一个pair，告诉我们插入操作是否成功。
    // pair的first成员是一个迭代器，指向具有给定关键字的元素；second成员是一个bool值，指出元素是插入成功还是已经存在于容器中。
    // 如果关键字已在容器中，则insert什么事情也不做，且返回值中的bool部分为false。如果关键字不存在，元素被插入容器中，且bool值为true。
    auto ret = word_count.insert({"world",2});
    if (!ret.second) // world已经在word_count中
    {
        ++ret.first->second; // 递增计数器，也就是递增word_count指定关键字的值，等价的表达式为 ++((ret.first)->second);
    }
    
    // 展开递增语句 ++((ret.first)->second);
    // ret保存insert操作的返回值，是个pair
    // ret.first是pair第一个成员，是个map迭代器，指向具有给定关键字的元素
    // ret.first-> 解引用此迭代器，提取map中的元素，元素也是一个pair。
    // ret.first->second map中元素的值部分。
    // ++ret.first->second 递增此值。

    // 向multiset或multimap中添加元素
    // 对允许重复关键字的容器，接受单个元素的insert操作返回一个指向新元素的迭代器。
    // 这里无须返回一个bool值，因为insert总是向这类容器中加入一个新元素。
    multimap<string,string> authors;
    authors.insert({"唐浩明","曾国藩"}); // 插入第一个元素，关键字为唐浩明
    authors.insert({"唐浩明","张之洞"}); // 插入第二个元素，关键字也为唐浩明

    return 0;
}